package controleur;

import controleur.exceptions.AucunIntervenantException;
import controleur.exceptions.AucuneMatiereException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

import modele.*;
import modele.exceptions.*;

/**
 * Class Fonctions faisant partie du contrôleur regroupant des fonctions qui seront
 * utilisées par le contrôleur, cela permet d'éviter de la redondance de code
 * et d'alourdir la lecture du code de certains traitements d'actions
 */
public class Fonctions {

    /**
     * Permet de préparer le menu comportant chaque fonctionnalité à laquelle typePersonne peut accéder
     * @return On va associer une liste de titres qui seront affichés sur le menu aux noms des actions correspondantes
     */
    protected static ArrayList<ArrayList<String>> pagesAutorisees(String typePersonne) {
        ArrayList<ArrayList<String>> lesPages = new ArrayList<ArrayList<String>>();
        ArrayList<String> pages = new ArrayList<String>();
        ArrayList<String> libelles = new ArrayList<String>();
        lesPages.add(pages);
        lesPages.add(libelles);

        if (!typePersonne.equals("MembreAdministration")) {
            pages.add("profil");
            libelles.add("Profil");
        }

        if (!typePersonne.equals("MembreAdministration") && !typePersonne.equals("MaitreDeStage")) {
            if (typePersonne.equals("Etudiant")) {
                pages.add("retourMatiere");
            } else {
                pages.add("retoursMatiere");
            }

            libelles.add("Matieres");
        }

        if (typePersonne.equals("Etudiant")) {
            pages.add("retourTuteur");
            pages.add("retourMaitre");
            pages.add("retourAdmin");
            libelles.add("Retour tuteur");
            libelles.add("Retour maitre");
            libelles.add("Retour admin");
        }

        if (typePersonne.equals("MaitreDeStage")) {
            pages.add("ajoutModifMaitre");
            libelles.add("Modifier Profil");
        }

        if (typePersonne.equals("Intervenant") || typePersonne.equals("MaitreDeStage")) {
            pages.add("consulter");
            libelles.add("Consulter");
        }

        if (typePersonne.equals("MembreAdministration")) {
            pages.add("consulterAdmin");
            libelles.add("Consulter");
            pages.add("gestionMaitre");
            libelles.add("Gérer maitres");
        }

        pages.add("profilIntervenant");
        libelles.add("Intervenants");

        return lesPages;
    }

    /**
     * Renvoyer la liste des matières : toutes les matières d'une formation si on est un étudiant,
     * toutes les matières d'un enseignant si on connecté comme tel.
     */
    protected static List<Matiere> getMatieresSelonIdentifie(HttpServletRequest request) throws SQLException {
        List<Matiere> lesMatieres = null;

        String typePersonne = (String) request.getSession().getAttribute("typePersonne");

        if (request.getAttribute("page") == null) {
            //Si le livret d'un étudiant n'est pas consulté par un non-étudiant
            if (typePersonne.equals("Intervenant")) //Si l'enseignant veut voir les retours sur sa matière
            {
                Intervenant i = (Intervenant) request.getSession().getAttribute("identifie");
                lesMatieres = Intervenant.getMatieres(i.getId());
            } else if (typePersonne.equals("Etudiant")) {
                //Si l'étudiant veut éditer son retour sur matière
                Etudiant e = (Etudiant) request.getSession().getAttribute("identifie");

                try {
                    lesMatieres = Matiere.getMatieres(e.getFormation());
                } catch (InformationIndisponibleException ex) {/*Ce cas ne peut pas arriver dans ce contexte*/

                }
            } else if (typePersonne.equals("MembreAdministration")) //Cette liste n'a pas vraiment d'importance.
            {
                lesMatieres = Matiere.getToutesLesMatieres();
            }

        } else //Si le livret de l'étudiant est consulté par un non-étudiant
        {
            Etudiant e = (Etudiant) request.getAttribute("etudiantConsulte");

            try {
                lesMatieres = Matiere.getMatieres(e.getFormation());
            } catch (InformationIndisponibleException ex) {/*Ce cas ne peut pas arriver dans ce contexte*/

            }
        }

        return lesMatieres;
    }

    protected static RetourSurEtudiant getRetourTuteur(HttpServletRequest request) throws PasDeTuteurException, SQLException {
        Etudiant etudiantConcerne = null;

        //S'il s'agit d'un étudiant qui consulte son livret
        if (request.getAttribute("page") == null) {
            etudiantConcerne = (Etudiant) request.getSession().getAttribute("identifie");
        } //S'il s'agit d'un non étudiant qui consulte un livret d'étudiant
        else {
            etudiantConcerne = (Etudiant) request.getAttribute("etudiantConsulte");
        }

        RetourSurEtudiant resultat = null;

        resultat = (RetourSurEtudiant) etudiantConcerne.getRetourTuteur();

        return resultat;
    }

    protected static RetourSurEtudiant getRetourMaitre(HttpServletRequest request) throws PasDeMaitreDeStageException, SQLException {
        Etudiant etudiantConcerne = null;

        //S'il s'agit d'un étudiant qui consulte son livret
        if (request.getAttribute("page") == null) {
            etudiantConcerne = (Etudiant) request.getSession().getAttribute("identifie");
        } //S'il s'agit d'un non étudiant qui consulte un livret d'étudiant
        else {
            etudiantConcerne = (Etudiant) request.getAttribute("etudiantConsulte");
        }

        RetourSurEtudiant resultat = null;

        resultat = (RetourSurEtudiant) etudiantConcerne.getRetourMaitreDeStage();

        return resultat;

    }

    protected static RetourSurEtudiant getRetourAdmin(HttpServletRequest request) throws SQLException {
        Etudiant etudiantConcerne = null;

        //S'il s'agit d'un étudiant qui consulte son livret
        if (request.getAttribute("page") == null) {
            etudiantConcerne = (Etudiant) request.getSession().getAttribute("identifie");
        } //S'il s'agit d'un non étudiant qui consulte un livret d'étudiant
        else {
            etudiantConcerne = (Etudiant) request.getAttribute("etudiantConsulte");
        }

        return (RetourSurEtudiant) etudiantConcerne.getRetourAdmin();
    }

    protected static Retour getRetourMatiere(HttpServletRequest request) throws MatiereInexistanteException, SQLException {
        Retour resultat = null;

        Etudiant etu = null;

        //Si l'étudiant consulte son livret
        if (request.getAttribute("page") == null) {
            etu = (Etudiant) request.getSession().getAttribute("identifie");
        } else //Si le livret est consulté par un non-étudiant
        {
            etu = (Etudiant) request.getAttribute("etudiantConsulte");
        }

        resultat = (Retour) etu.getRetour((Integer) request.getAttribute("idMatiere"));

        return resultat;
    }
    
    /*
     * Positionner en attribut de la requête la liste des étudiants d'une année et d'une formation,
     * d'un maitre de stage, ou d'un tuteur
     */
    protected static void getEtudiants(HttpServletRequest request) throws SQLException {

        String nomAnnee = (String) request.getAttribute("nomAnnee");
        int idFormation = (Integer) request.getAttribute("idFormation");

        List<Etudiant> le = null;

        if (request.getParameter("idIntervenant") == null) {
            if (request.getParameter("idMaitre") == null) //On veut afficher tous les étudiants de l'année et de la formation
            {
                le = Etudiant.getEtudiants(nomAnnee, idFormation);
            } else //On veut afficher les étudiants du maitre
            {
                le = Etudiant.getEtudiants(nomAnnee, idFormation, MaitreDeStage.class, Integer.parseInt(request.getParameter("idMaitre")));
            }
        } else //On veut afficher les étudiants du tuteur
        {
            le = Etudiant.getEtudiants(nomAnnee, idFormation, Intervenant.class, Integer.parseInt(request.getParameter("idIntervenant")));
        }

        request.setAttribute("etudiants", le);
    }

    protected static void getEtudiantsSansMaitre(HttpServletRequest request) throws SQLException {

        getAnnees(request);

        String nomAnnee = (String) request.getAttribute("nomAnnee");

        List<Etudiant> le = Etudiant.getEtudiantsSansMaitre(nomAnnee);

        request.setAttribute("etudiants", le);
    }

    /**
     * Positionner en attribut de la requête la liste des années, avec par défaut la première année sélectionnée
     */
    protected static void getAnnees(HttpServletRequest request) throws SQLException {
        List<Annee> annees = Annee.getToutesLesAnnees();

        request.setAttribute("annees", annees);

        request.setAttribute("nomAnnee", request.getParameter("nomAnnee"));

        //Si on vient d'arriver, chargement par défaut de la première année
        if (request.getAttribute("nomAnnee") == null) {
            request.setAttribute("nomAnnee", annees.get(0).getNom());
        }

    }

    protected static void getIntervenants(HttpServletRequest request) throws AucunIntervenantException, IntervenantInexistantException, SQLException {
        List<Intervenant> li = Intervenant.getTousLesIntervenants();

        if (li.size() > 0) {
            //S'il y a des intervenants

            request.setAttribute("intervenants", li);

            //Récupération de l'intervenant demandé passé en paramètre
            String idIntervenantString = request.getParameter("idIntervenant");
            if (idIntervenantString != null) {
                request.setAttribute("idIntervenant", Integer.parseInt(idIntervenantString));
            } else //Si on vient d'arriver, chargement par défaut du premier intervenant
            {
                request.setAttribute("idIntervenant", li.get(0).getId());
            }

            determinerIntervenantProfil(request);
        } else {
            throw new AucunIntervenantException();
        }
    }

    private static void determinerIntervenantProfil(HttpServletRequest request) throws IntervenantInexistantException, SQLException {
        //idIntervenant ne peut pas être null car on l'a rempli avant quand on arrive ici
        int idIntervenant = (Integer) request.getAttribute("idIntervenant");

        Intervenant i = Intervenant.getIntervenant(idIntervenant);
        request.setAttribute("profilConsulte", i);

    }

    protected static void getMaitre(HttpServletRequest request) throws MaitreDeStageInexistantException, SQLException {
        //Pour faire les tests ${empty idMaitre}
        request.setAttribute("idMaitre", request.getParameter("idMaitre"));

        //Est-ce qu'on est en création de maitre?
        if (request.getParameter("idMaitre") != null) {
            //On est en modification de maitre (par l'admin)

            int idMaitre = Integer.parseInt(request.getParameter("idMaitre"));

            MaitreDeStage ms = MaitreDeStage.getMaitreDeStage(idMaitre);
            request.setAttribute("maitre", ms);

        }

        //Est-ce que le maitre veut se modifier lui même ?
        if (request.getSession().getAttribute("typePersonne").equals("MaitreDeStage")) {
            MaitreDeStage ms = (MaitreDeStage) request.getSession().getAttribute("identifie");
            request.setAttribute("maitre", ms);
            request.setAttribute("idMaitre", ms.getId());

        }

    }

    protected static void getMatieres(HttpServletRequest request) throws AucuneMatiereException, SQLException {
        //Créer la liste des matières en fonction du type de Personne
        List<Matiere> lm = Fonctions.getMatieresSelonIdentifie(request);

        if (lm.size() > 0) {
            //S'il y a des matières

            request.setAttribute("matieres", lm);

            //Récupération de la matière demandée passée en paramètre
            String idMatiereString = request.getParameter("idMatiere");
            if (idMatiereString != null) {
                request.setAttribute("idMatiere", Integer.parseInt(idMatiereString));
            } else //Si on vient d'arriver, chargement par défaut de la première matière
            {
                request.setAttribute("idMatiere", lm.get(0).getId());
            }
        } else {
            throw new AucuneMatiereException();
        }
    }

    protected static void getFormations(HttpServletRequest request) throws SQLException {
        List<Formation> formations = Formation.getToutesLesFormations();

        request.setAttribute("formations", formations);

        String idFormation = request.getParameter("idFormation");
        if (idFormation != null) {
            request.setAttribute("idFormation", Integer.parseInt(idFormation));
        } else //Si on vient d'arriver, chargement par défaut de la première formation
        {
            request.setAttribute("idFormation", formations.get(0).getId());
        }
    }

    /**
     * Permet de générer le menu des formations de consulterAdmin.jsp en associant l'id de la formation
     * avec son libellé qui va s'afficher sur le menu
     */
    protected static Map<Integer, String> lesFormations(HttpServletRequest request) {
        HashMap<Integer, String> lesFormations = new HashMap<Integer, String>();

        List<Formation> forms = (List<Formation>) request.getAttribute("formations");

        for (Formation f : forms) {
            lesFormations.put(f.getId(), f.getNomFormation());
        }

        return lesFormations;
    }

    /**
     * Affecte un maitre de stage aux étudiants sélectionnés
     * @param ms : le maitre de stage à affecter
     */
    protected static void affecterEtudiants(HttpServletRequest request, MaitreDeStage ms) throws SQLException {
        try {

            for (int i = 0; request.getParameter("idEtudiant" + i) != null; i++) {
                int idEtudiant = Integer.parseInt(request.getParameter("idEtudiant" + i));
                Etudiant e = Etudiant.getEtudiant(idEtudiant);
                e.affecterMaitreDeStage(ms);

            }
        } catch (EtudiantInexistantException e) {/*Ce cas ne peut pas arriver dans ce contexte.*/

        } catch (IntervenantInexistantException e) {/*Ce cas ne peut pas arriver dans ce contexte.*/

        } catch (FormationInexistanteException e) {/*Ce cas ne peut pas arriver dans ce contexte.*/

        } catch (MaitreDeStageInexistantException e) {/*Ce cas ne peut pas arriver dans ce contexte.*/

        }
    }

    /**
     * @param erreur "erreur" si un étudiant modifie son retour, "sousErreur" si un autre consulte son retour
     */
    protected static void enregistrerRetour(String erreur, HttpServletRequest request) {

        Retour r = (Retour) request.getSession().getAttribute("retour");

        try {

            r.setTexte(request.getParameter("texteretour"));
            request.setAttribute("enregistrerOk", "oui");
        } catch (SQLException e) {
            request.setAttribute(erreur, "Erreur de la base de données.");
        }

    }
}
